
import * as utc from "../util/utc.js";
import {nav1hr, nav3hr, newProduct, resolveValidTime} from "./productUtils.js";
import {tr} from "../ux/translations.js";
import * as sources from "./sources.js";
import {scalarProduct} from "./scalarProduct.js";
import {ø} from "../util/objects.js";
import {createUnitDescriptors} from "../util/units.js";
import {createNO2Palette} from "../palette/no2.js";
import {gaiaPath} from "./gaia.js";
import {createPMxPalette} from "../palette/pmx.js";


let palettes = {};

function camsPath(attr, layer, alignment) {
    const validTime = resolveValidTime(attr.time_cursor, alignment);
    const isCurrent = attr.time_cursor === "current";
    const dir = isCurrent ? "current" : utc.print(validTime, "{YYYY}/{MM}/{DD}");
    const stamp = isCurrent ? "current" : utc.print(validTime, "{hh}{mm}");
    const file = `${stamp}-${layer}-cams.epak`;
    return gaiaPath("data/cams", dir, file);
}

function newCAMSProduct() {
    const base = {
        sourceHTML: sources.cams,
    };
    return ø(newProduct(), base);
}

export function createPM1Layer(attr) {
    const base = ø(newCAMSProduct(), nav1hr(attr.time_cursor));
    return ø(base, {
        type: "pm1",
        descriptionHTML: {
            name: tr`Particulate Matter < 1 µm`,
            qualifier: ` @ ${tr`Surface`}`,
        },
        paths: [camsPath(attr, "pm1", base.alignment())],
        builder: file => scalarProduct(file, /pm1/, {hasMissing: false}),
        unitDescriptors: createUnitDescriptors({
            "µg/m^3": {convert: x => x * 1e9, precision: 0},
        }),
        alpha: {single: 160, animated: 140},
        scale: palettes.pmx ??= createPMxPalette(),
    });
}

export function createPM2p5Layer(attr) {
    const base = ø(newCAMSProduct(), nav1hr(attr.time_cursor));
    return ø(base, {
        type: "pm2.5",
        descriptionHTML: {
            name: tr`Particulate Matter < 2.5 µm`,
            qualifier: ` @ ${tr`Surface`}`,
        },
        paths: [camsPath(attr, "pm2p5", base.alignment())],
        builder: file => scalarProduct(file, /pm2p5/, {hasMissing: false}),
        unitDescriptors: createUnitDescriptors({
            "µg/m^3": {convert: x => x * 1e9, precision: 0},
        }),
        alpha: {single: 160, animated: 140},
        scale: palettes.pmx ??= createPMxPalette(),
    });
}

export function createPM10Layer(attr) {
    const base = ø(newCAMSProduct(), nav1hr(attr.time_cursor));
    return ø(base, {
        type: "pm10",
        descriptionHTML: {
            name: tr`Particulate Matter < 10 µm`,
            qualifier: ` @ ${tr`Surface`}`,
        },
        paths: [camsPath(attr, "pm10", base.alignment())],
        builder: file => scalarProduct(file, /pm10/, {hasMissing: false}),
        unitDescriptors: createUnitDescriptors({
            "µg/m^3": {convert: x => x * 1e9, precision: 0},
        }),
        alpha: {single: 160, animated: 140},
        scale: palettes.pmx ??= createPMxPalette(),
    });
}

export function createNO2Layer(attr) {
    const base = ø(newCAMSProduct(), nav3hr(attr.time_cursor));
    return ø(base, {
        type: "no2",
        descriptionHTML: {
            name: tr`Nitrogen Dioxide`,
            qualifier: ` @ ${tr`Surface`}`,
        },
        paths: [camsPath(attr, "no2", base.alignment())],
        builder: file => scalarProduct(file, /no2/, {hasMissing: false}),
        unitDescriptors: createUnitDescriptors({
            "ppb": {convert: x => x * 1e9, precision: 2},
            "ppm": {convert: x => x * 1e6, precision: 2},
            "µg/m^3": {convert: x => x * 1e6 * 1880, precision: 0},
        }),
        alpha: {single: 160, animated: 120},
        scale: palettes.no2 ??= createNO2Palette(),
    });
}

/*
export function createCOLayer(attr) {
    const stride = 3;
    return buildProduct({
        type: "co",
        descriptionHTML: localize({
            name: {en: "CO", ja: ""},
            qualifier: ""
        }),
        sourceHTML: sources.cams,
        paths: [camsPath(attr, "co", stride)],
        validTime: function() {
            return camsValidTime(attr.time_cursor, stride);
        },
        navigate: function(step) {
            return camsStep(this.validTime(), stride, step);
        },
        builder: function(file) {
            return scalarProduct(file, /co|VAR192.*!/, {hasMissing: false, transform: data => {
                for (let i = 0; i < data.length; i++) {
                    data[i] *= 1e9;
                }
            }});
        },
        unitDescriptors: {  // CO Surface Concentration in ppbw, units: 1e-9
            "ppbw": {convert: x => x,        precision: 0},
            "ppmw": {convert: x => x / 1000, precision: 2},
        },
        alpha: {single: 160, animated: 140},
        scale: require("./palette/cosc")(),
    });
}

export function createO3Layer(attr) {
    const stride = 3;
    return buildProduct({
        type: "o3",
        descriptionHTML: localize({
            name: {en: "O3", ja: ""},
            qualifier: ""
        }),
        sourceHTML: sources.cams,
        paths: [camsPath(attr, "go3", stride)],
        validTime: function() {
            return camsValidTime(attr.time_cursor, stride);
        },
        navigate: function(step) {
            return camsStep(this.validTime(), stride, step);
        },
        builder: function(file) {
            return scalarProduct(file, /go3/, {hasMissing: false});
        },
        unitDescriptors: {
            "ppbw": {convert: x => x * 1e9, precision: 0},
        },
        alpha: {single: 160, animated: 140},
        scale: palette.buildScaleFromSegments([0, 600e-9], [
            [0,        [  0,   0,   0]],
            [600e-9,   [255, 255, 255]]
        ], 1000),
    });
}

export function createSO2Layer(attr) {
    const stride = 3;
    return buildProduct({
        type: "so2",
        descriptionHTML: localize({
            name: {en: "SO2", ja: ""},
            qualifier: ""
        }),
        sourceHTML: sources.cams,
        paths: [camsPath(attr, "so2", stride)],
        validTime: function() {
            return camsValidTime(attr.time_cursor, stride);
        },
        navigate: function(step) {
            return camsStep(this.validTime(), stride, step);
        },
        builder: function(file) {
            return scalarProduct(file, /so2/, {hasMissing: false});
        },
        unitDescriptors: {
            "µg/m^3": {convert: x => x * 1e9 * 2.86, precision: 2},
            "ppbw":   {convert: x => x * 1e9,        precision: 0},
        },
        alpha: {single: 160, animated: 140},
        scale: require("./palette/so2ppb")(),
    });
}
*/
